package team.seekers.hula.course.courseUser.service;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import team.seekers.hula.common.entity.PageResult;
import team.seekers.hula.common.entity.enums.CourseRoleEnum;
import team.seekers.hula.course.course.service.CourseService;
import team.seekers.hula.course.courseUser.dao.CourseUserDao;
import team.seekers.hula.course.courseUser.entity.dao.CourseUserDO;
import team.seekers.hula.course.courseUser.entity.dto.*;
import team.seekers.hula.course.courseUser.entity.vo.*;
import team.seekers.hula.course.courseUser.mapper.CourseUserMapper;
import team.seekers.hula.course.resource.examSubmit.service.ExamRecordManageService;
import team.seekers.hula.course.structure.section.service.SectionProgressService;
import team.seekers.hula.course.structure.section.service.SectionService;
import team.seekers.hula.user.user.entity.dao.UserDO;
import team.seekers.hula.user.user.entity.dto.UserInfoDTO;
import team.seekers.hula.user.user.entity.vo.UserInfoVO;
import team.seekers.hula.user.user.service.UserService;

import javax.annotation.Resource;
import java.util.*;

@Service
public class CourseUserService {


    @Autowired
    private CourseUserDao courseUserDao;

    @Autowired
    private CourseService courseService;

    @Autowired
    private SectionService sectionService;

    @Autowired
    private SectionProgressService sectionProgressService;

    @Autowired
    private UserService userService;

    @Resource
    private CourseUserMapper courseUserMapper;

    @Resource
    private ExamRecordManageService examRecordManageService;

//    public PageResult<CourseUserListVO> page(CourseUserReqListDTO reqDTO) {
//
//
//        LambdaQueryChainWrapper<CourseUserDO> wrapper = courseUserDao.lambdaQuery().select(
//                        CourseUserDO::getCourseId
//                ).eq(CourseUserDO::getUserId, reqDTO.getUserId());
//
//        Page<CourseUserDO> pageResult = wrapper.page(new Page<>(reqDTO.getPageNow(), reqDTO.getPageSize()));
//
//        List<String> courseIds = new ArrayList<>();
//        for (CourseUserDO record : pageResult.getRecords()) {
//            courseIds.add(record.getCourseId());
//        }
//
//        Map<String, CourseBasicInfoVO> map =  courseService.idsMapCourseBasicInfo(courseIds);
//
//        List<CourseUserListDTO> courseUserListDTOS;
//        if(reqDTO.getIsCollect() != null && reqDTO.getIsCollect()){
//            List<String> collectCourseIds = userService.queryAllCollectCourse(reqDTO.getUserId());
//            if(collectCourseIds.size() == 0){
//                return new PageResult<>();
//            }
//            if(reqDTO.getIsBuy() != null && !reqDTO.getIsBuy()){
//                // 处理已收藏未购买
//                collectCourseIds.removeAll(courseIds);
//                courseIds = collectCourseIds;
//            }else if (reqDTO.getIsBuy() == null){
//                courseIds = collectCourseIds;
//            }else {
//                // 处理已收藏已购买
//                for (int i = 0;i< courseIds.size();i++){
//                    if (!collectCourseIds.contains(courseIds.get(i))){
//                        courseIds.remove(i);
//                        i--;
//                    }
//                }
//            }
//            courseUserListDTOS = courseService.idsToCourseUserListDTOList(courseIds);
//        }else {
//            courseUserListDTOS = courseService.idsAndUserIdToCourseInfoAndProcessListDTOList(courseIds,reqDTO.getUserId());
//        }
//        return new PageResult<>(pageResult.getTotal(), courseUserListDTOS);
//    }

    public Map<String, Boolean> queryBuyStatusByCourseIdsAndUserId(List<String> courseIds, String userId) {
        HashMap<String, Boolean> map = new HashMap<>();
        for (String courseId : courseIds) {
            CourseUserDO one = courseUserDao.lambdaQuery()
                    .select(
                            CourseUserDO::getCourseId,
                            CourseUserDO::getUserId
                    )
                    .eq(CourseUserDO::getCourseId, courseId)
                    .eq(CourseUserDO::getUserId, userId)
                    .one();
            if(one != null){
                map.put(courseId,true);
            }else {
                map.put(courseId,false);
            }
        }
        return map;
    }

//    public PageResult<CourseUserManageListDTO> pageByBusinessId(CourseUserReqListDTO reqDTO) {
//        List<Long> userIds = businessClient.queryUserIdsByBusinessIdLikeNameOrPhone(
//                reqDTO.getBusinessId(),
//                reqDTO.getUsername(),
//                reqDTO.getPhone());
//
//
//        LambdaQueryChainWrapper<CourseUserDO> wrapper = courseUserDao.lambdaQuery().select(
//                        CourseUserDO::getId,
//                        CourseUserDO::getCourseId,
//                        CourseUserDO::getUserId,
//                        CourseUserDO::getScore,
//                        CourseUserDO::getProgress,
//                        CourseUserDO::getType
//                ).in(CourseUserDO::getUserId, userIds);
//
//        if(reqDTO.getType() != null){
//            wrapper.eq(CourseUserDO::getType, reqDTO.getType());
//        }
//
//        if(reqDTO.getIsOver() != null){
//            if(reqDTO.getIsOver())
//                wrapper.eq(CourseUserDO::getProgress,100);
//            else
//                wrapper.ne(CourseUserDO::getProgress,100);
//        }
//
//
//        Page<CourseUserDO> pageResult = wrapper.page(new Page<>(reqDTO.getPageNow(), reqDTO.getPageSize()));
//
//        ArrayList<Long> mapUserIds = new ArrayList<>();
//        ArrayList<Long> mapCourseIds = new ArrayList<>();
//        for (CourseUserDO record : pageResult.getRecords()) {
//            mapUserIds.add(record.getUserId());
//            mapCourseIds.add(record.getCourseId());
//        }
//        Map<Long, UserBasicInfoDTO> userInfoMap = userService.userIdsToUserBasicInfoDTOs(mapUserIds);
//        Map<Long, String> courseNameMap = courseService.idsToNameMap(mapCourseIds);
//
//
//        List<CourseUserManageListDTO> courseUserManageListDTOs = new ArrayList<>();
//        for (CourseUserDO record : pageResult.getRecords()) {
//            CourseUserManageListDTO courseUserManageListDTO = CourseUserManageListDTO.builder()
//                    .id(record.getId())
//                    .courseId(record.getCourseId())
//                    .userId(record.getUserId())
//                    .userName(userInfoMap.get(record.getUserId()).getName())
//                    .identity(userInfoMap.get(record.getUserId()).getIdentity())
//                    .phone(userInfoMap.get(record.getUserId()).getPhone())
//                    .courseName(courseNameMap.get(record.getCourseId()))
//                    .score(record.getScore())
//                    .progress(record.getProgress())
//                    .build();
//            courseUserManageListDTOs.add(courseUserManageListDTO);
//        }

//        courseUserManageListDTOs = courseService.queryCourseInfoAndProcessByCourseIdsAndUserIds(courseUserManageListDTOs);

//        List<CourseUserManageListDTO> courseUserManageListDTOS = new ArrayList<>();
//
//        for (CourseUserListDTO courseUserListDTO : courseUserListDTOS) {
//            CourseUserManageListDTO courseUserManageListDTO = new CourseUserManageListDTO();
//
//            courseUserManageListDTO.setCourseId(courseUserListDTO.getId());
//            courseUserManageListDTO.setCourseName(courseUserListDTO.getName());
//            courseUserManageListDTO.setSectionNum(courseUserListDTO.getSectionNum());
//            courseUserManageListDTO.setSectionLearnedNum(courseUserListDTO.getSectionLearnedNum());
//
//            courseUserManageListDTO.setUserId(courseUserListDTO.getUserId());
//            UserDTO userDTO = userClient.userIdToUser(courseUserListDTO.getUserId());
//            courseUserManageListDTO.setUserName(userDTO.getNickname());
//            courseUserManageListDTO.setIdentity(userDTO.getIdentity());
//
//            courseUserManageListDTOS.add(courseUserManageListDTO);
//
//        }
//        return new PageResult<>(pageResult.getTotal(), courseUserManageListDTOs);
//    }

    public List<CourseUserBindInfoListVO> listUserBindCourseList(String userId) {
        LambdaQueryChainWrapper<CourseUserDO> wrapper = courseUserDao.lambdaQuery().select(
                CourseUserDO::getCourseId,
                CourseUserDO::getRole
        ).eq(CourseUserDO::getUserId, userId);

        List<CourseUserDO> list =wrapper.list();
        ArrayList<CourseUserBindInfoListVO> courseUserBindInfoListVOS = new ArrayList<>();
        for (CourseUserDO courseUserDO : list) {
            CourseUserBindInfoListVO build = CourseUserBindInfoListVO.builder()
                    .courseId(courseUserDO.getCourseId())
                    .courseName(courseService.idToName(courseUserDO.getCourseId()))
                    .courseDescription(courseService.idToDescription(courseUserDO.getCourseId()))
                    .role(CourseRoleEnum.getByType(courseUserDO.getRole()).getName())
                    .build();
            courseUserBindInfoListVOS.add(build);
        }
        return courseUserBindInfoListVOS;
    }

    public List<String> listUserBindCourseIdList(String userId, Integer role) {
        List<CourseUserDO> list =courseUserDao.lambdaQuery().select(
                CourseUserDO::getCourseId
        ).eq(CourseUserDO::getUserId, userId).ge(CourseUserDO::getRole,role).list();
        ArrayList<String> courseIds = new ArrayList<>();
        for (CourseUserDO courseUserDO : list) {
            courseIds.add(courseUserDO.getCourseId());
        }
        return courseIds;
    }

    public void updateCourseScore(String courseId, String userId, int score) {
        courseUserDao.lambdaUpdate()
                .eq(CourseUserDO::getCourseId,courseId)
                .eq(CourseUserDO::getUserId,userId)
                .update();
    }

    public void bindCourseUser(String courseId, String userId) {
        CourseUserDO courseUserDO = new CourseUserDO();
        courseUserDO.setCourseId(courseId);
        courseUserDO.setUserId(userId);
        courseUserDao.save(courseUserDO);
    }

    public void collectOrCancel(String courseId, String userId) {
        Boolean isCancel = userService.collectCourseOrCancel(userId, courseId);
        // TODO 课程收藏数量统计
    }


    public void syncProgress() {
        List<CourseUserDO> courseUserDOList = courseUserDao.lambdaQuery().select(
                CourseUserDO::getId,
                CourseUserDO::getCourseId,
                CourseUserDO::getUserId,
                CourseUserDO::getProgress
        ).list();
        for (CourseUserDO courseUserDO : courseUserDOList) {
            Integer progress = courseService.queryProgressByCourseIdAndUserId(courseUserDO.getCourseId(),courseUserDO.getUserId());
            courseUserDO.setProgress(Math.max(progress,courseUserDO.getProgress()));
        }
        courseUserDao.updateBatchById(courseUserDOList);
    }

    public CourseUserManageInfoVO getProgressInfoByCourseUserId(String courseId,String userId) {
        CourseUserDO courseUserDO = courseUserDao.lambdaQuery()
                .eq(CourseUserDO::getCourseId,courseId)
                .eq(CourseUserDO::getUserId,userId)
                .one();

        UserInfoVO userInfoVO = userService.getInfoVO(courseUserDO.getUserId());

        return CourseUserManageInfoVO.builder()
                .id(courseUserDO.getId())
                .courseId(courseUserDO.getCourseId())
                .userId(courseUserDO.getUserId())
                .userName(userInfoVO.getNickname())
                .tel(userInfoVO.getTel())
                .courseName(courseService.idToName(courseUserDO.getCourseId()))
                .progress(courseUserDO.getProgress())
                .lastSectionId(StringUtils.isNotBlank(courseUserDO.getLastSectionId()) ? courseUserDO.getLastSectionId() : sectionService.getFirstId(courseUserDO.getCourseId()))
                .lastSectionName(StringUtils.isNotBlank(courseUserDO.getLastSectionId()) ? sectionService.getNameById(courseUserDO.getLastSectionId()) : "无学习记录")
                .lastProgress(courseUserDO.getLastProgress())
                .build();
    }

    public boolean checkCourseOver(List<Long> courseIds, Long userId) {
        return true;
    }

    public PageResult<CourseEvaluationListVO> pageEvaluation(CourseEvaluationReqListDTO listDTO) {
        LambdaQueryChainWrapper<CourseUserDO> wrapper = courseUserDao.lambdaQuery().select(
                CourseUserDO::getUserId,
                CourseUserDO::getGmtModified,
                CourseUserDO::getComment
        ).eq(CourseUserDO::getCourseId, listDTO.getCourseId());

        Page<CourseUserDO> pageResult = wrapper.page(new Page<>(listDTO.getPageNow(), listDTO.getPageSize()));

        if(pageResult.getRecords().size() == 0){
            return new PageResult<>();
        }

        List<String> userIds = new ArrayList<>();
        for (CourseUserDO record : pageResult.getRecords()) {
            userIds.add(record.getUserId());
        }

        Map<String, UserInfoDTO> userInfoDTOMap = userService.userIdsToUserInfoDTOs(userIds);

        List<CourseEvaluationListVO> evaluationListVOS = new ArrayList<>();
        for (CourseUserDO record : pageResult.getRecords()) {
            evaluationListVOS.add(CourseEvaluationListVO.builder()
                    .content(record.getComment())
                    .nickname(userInfoDTOMap.get(record.getUserId()).getNickname())
                    .avatar(userInfoDTOMap.get(record.getUserId()).getAvatar())
                    .gmtCreate(record.getGmtModified()).build());

        }

        return new PageResult<>(pageResult.getTotal(), evaluationListVOS);
    }

    public PageResult<CourseUserManageListVO> page(CourseUserPageQueryDTO userQuery) {

        // 先条件过滤courseUser
        HashMap<String, CourseUserDO> map = new HashMap<>();
        LambdaQueryChainWrapper<CourseUserDO> courseUserQueryWrapper = courseUserDao.lambdaQuery();
        if(userQuery.getRole() != null) {
            courseUserQueryWrapper.eq(CourseUserDO::getRole,userQuery.getRole());
        }
        courseUserQueryWrapper.eq(CourseUserDO::getCourseId,userQuery.getCourseId());
        List<String> userId = new ArrayList<>();
        List<CourseUserDO> list = courseUserQueryWrapper.list();
        if(list.size() == 0){
            return new PageResult<>();
        }
        for (CourseUserDO courseUserDO : list) {
            userId.add(courseUserDO.getUserId());
            map.put(courseUserDO.getUserId(),courseUserDO);
        }
        // user表查询用户信息
        LambdaQueryChainWrapper<UserDO> userWrapper = userService.lambdaQuery();
        List<CourseUserManageListVO> resList = new ArrayList<>();
        Optional.of(userQuery).map(CourseUserPageQueryDTO::getNickname).ifPresent(nickName -> {
            userWrapper.likeRight(UserDO::getNickname,nickName);
        });
        Optional.of(userQuery).map(CourseUserPageQueryDTO::getTel).ifPresent(tel -> {
            userWrapper.likeRight(UserDO::getTel, tel);
        });
        if(userId.size()!=0){
            userWrapper.in(UserDO::getId,userId);
        }
        Page<UserDO> page = userWrapper.page(new Page<>(userQuery.getPageNow(), userQuery.getPageSize()));
        for (UserDO userDO : page.getRecords()) {
            CourseUserDO courseUserDO = map.get(userDO.getId());
            CourseUserManageListVO build = CourseUserManageListVO.builder().id(courseUserDO.getId())
                    .nickname(userDO.getNickname())
                    .role(courseUserDO.getRole())
                    .tel(userDO.getTel())
                    .hulaCoin(courseUserDO.getHulaCoin())
                    .courseId(courseUserDO.getCourseId())
                    .userId(userDO.getId())
                    .gmtCreate(courseUserDO.getGmtCreate()).build();
            resList.add(build);
        }

        return new PageResult<>(page.getTotal(),page.getSize(),resList);
    }

    public PageResult<CourseUserManageListVO> pageNotIn(CourseUserPageQueryDTO userQuery) {
        // 先排除所有已经在知桨里面的
        List<CourseUserDO> courseUserDOList = courseUserDao.lambdaQuery().select(CourseUserDO::getUserId).eq(CourseUserDO::getCourseId, userQuery.getCourseId()).list();
        ArrayList<String> joinedUserIds = new ArrayList<>();
        for (CourseUserDO courseUserDO : courseUserDOList) {
            joinedUserIds.add(courseUserDO.getUserId());
        }

        // 剩下的条件查询
        // user表查询用户信息
        LambdaQueryChainWrapper<UserDO> userWrapper = userService.lambdaQuery();
        List<CourseUserManageListVO> resList = new ArrayList<>();
        Optional.of(userQuery).map(CourseUserPageQueryDTO::getRole).ifPresent(role -> {
            userWrapper.eq(UserDO::getRole,role);
        });
        Optional.of(userQuery).map(CourseUserPageQueryDTO::getNickname).ifPresent(nickName -> {
            userWrapper.likeRight(UserDO::getNickname,nickName);
        });
        Optional.of(userQuery).map(CourseUserPageQueryDTO::getTel).ifPresent(tel -> {
            userWrapper.likeRight(UserDO::getTel, tel);
        });
        if(joinedUserIds.size()!=0){
            userWrapper.notIn(UserDO::getId,joinedUserIds);
        }
        Page<UserDO> page = userWrapper.page(new Page<>(userQuery.getPageNow(), userQuery.getPageSize()));
        for (UserDO userDO : page.getRecords()) {
            CourseUserManageListVO build = CourseUserManageListVO.builder()
                    .nickname(userDO.getNickname())
                    .role(userDO.getRole().getValue())
                    .tel(userDO.getTel())
                    .userId(userDO.getId())
                    .gmtCreate(userDO.getGmtCreate()).build();
            resList.add(build);
        }

        return new PageResult<>(page.getTotal(),page.getSize(),resList);
    }

    public void updateRole(CourseUserUpdateDTO userUpdateDTO) {
        CourseUserDO courseUserDO = new CourseUserDO();
        courseUserDO.setId(userUpdateDTO.getId());
        courseUserDO.setRole(userUpdateDTO.getRole());
        courseUserDao.updateById(courseUserDO);
    }

    public Integer countBuy(String id) {
        return courseUserDao.lambdaQuery().eq(CourseUserDO::getCourseId,id).count();
    }
    public Integer countFixed(String id) {
        return courseUserDao.lambdaQuery().eq(CourseUserDO::getCourseId,id).eq(CourseUserDO::getIsFixed,1).count();
    }


    public List<String> getFixedCourseIds(String userId) {
        List<CourseUserDO> courseUserDOList = courseUserDao.lambdaQuery()
                .select(CourseUserDO::getCourseId)
                .eq(CourseUserDO::getIsFixed, 1)
                .eq(CourseUserDO::getUserId, userId)
                .list();

        ArrayList<String> courseIds = new ArrayList<>();
        for (CourseUserDO courseUserDO : courseUserDOList) {
            courseIds.add(courseUserDO.getCourseId());
        }
        return courseIds;
    }

    public Map<String, CourseUserManageListVO> mapManageVOByUserIdAndCourseIds(CourseUserListDTO listDTO) {
        HashMap<String, CourseUserManageListVO> map = new HashMap<>();

        LambdaQueryChainWrapper<CourseUserDO> query = courseUserDao.lambdaQuery().eq(CourseUserDO::getUserId, listDTO.getUserId());

        if(listDTO.getRole() != null){
            query.eq(CourseUserDO::getRole,listDTO.getRole());
        }

        if(listDTO.getIsFixed() != null){
            query.eq(CourseUserDO::getIsFixed,listDTO.getIsFixed());
        }

        List<CourseUserDO> courseUserDOList = query.list();
        for (CourseUserDO record : courseUserDOList) {
            CourseUserManageListVO build = CourseUserManageListVO.builder()
                    .role(record.getRole())
                    .isFixed(record.getIsFixed())
                    .userId(record.getId())
                    .hulaCoin(record.getHulaCoin())
                    .gmtCreate(record.getGmtCreate()).build();
            map.put(record.getCourseId(),build);
        }
        return map;
    }

    public Map<String, CourseUserListVO> mapVOByUserId(CourseUserListDTO listDTO) {
        LambdaQueryChainWrapper<CourseUserDO> query = courseUserDao.lambdaQuery()
                .eq(CourseUserDO::getUserId, listDTO.getUserId());

        if(listDTO.getRole() != null){
            query.eq(CourseUserDO::getRole,listDTO.getRole());
        }

        if(listDTO.getIsFixed() != null){
            query.eq(CourseUserDO::getIsFixed,listDTO.getIsFixed());
        }

        HashMap<String, CourseUserListVO> map = new HashMap<>();
        List<CourseUserDO> courseUserDOList = query.list();
        for (CourseUserDO record : courseUserDOList) {
            CourseUserListVO build = CourseUserListVO.builder()
                    .courseId(record.getCourseId())
                    .progress(record.getProgress())
                    .lastSectionId(record.getLastSectionId()).build();
            map.put(record.getCourseId(),build);
        }
        return map;
    }



    public void bind(CourseUserBindDTO islandUserBindDTO) {

        CourseUserDO courseUserDO = CourseUserDO
                .builder()
                .userId(islandUserBindDTO.getUserId())
                .courseId(islandUserBindDTO.getCourseId()).role(0)
                .build();
        courseUserDao.save(courseUserDO);

    }

    public void fixedOrCancel(String islandId, String userId) {
        CourseUserDO courseUserDO = courseUserDao.lambdaQuery().select(CourseUserDO::getId, CourseUserDO::getIsFixed)
                .eq(CourseUserDO::getCourseId, islandId).eq(CourseUserDO::getUserId, userId).one();

        courseUserDO.setIsFixed(courseUserDO.getIsFixed() == 1 ? 0 : 1);
        courseUserDao.updateById(courseUserDO);
    }

    public Map<String, Integer> mapProgressByCourseIds(List<String> courseIds, String userId) {
        List<CourseUserDO> list = courseUserDao.lambdaQuery()
                .select(CourseUserDO::getProgress, CourseUserDO::getCourseId)
                .eq(CourseUserDO::getUserId, userId)
                .in(CourseUserDO::getCourseId, courseIds)
                .list();

        HashMap<String, Integer> hashMap = new HashMap<>();
        for (CourseUserDO courseUserDO : list) {
            hashMap.put(courseUserDO.getCourseId(),courseUserDO.getProgress() == null ? 0 : courseUserDO.getProgress());
        }

        return hashMap;
    }

    public void updateProgress(String sectionId, Integer progress, String userId) {
        String courseId = sectionService.getCourseIdById(sectionId);

        // 更新总进度并记录最新记录
        Integer newProgress = sectionProgressService.countProgressUpdate(courseId,userId);

        courseUserDao.lambdaUpdate()
                .set(CourseUserDO::getLastSectionId,sectionId)
                .set(CourseUserDO::getLastProgress,progress)
                .set(CourseUserDO::getProgress,newProgress)
                .eq(CourseUserDO::getCourseId,courseId)
                .eq(CourseUserDO::getUserId,userId)
                .update();
    }

    public Map<String, Boolean> queryFixedStatusByCourseIdsAndUserId(ArrayList<String> courseIds, String userId) {
        HashMap<String, Boolean> map = new HashMap<>();
        for (String courseId : courseIds) {
            CourseUserDO one = courseUserDao.lambdaQuery()
                    .select(
                            CourseUserDO::getCourseId,
                            CourseUserDO::getUserId,
                            CourseUserDO::getIsFixed
                    )
                    .eq(CourseUserDO::getCourseId, courseId)
                    .eq(CourseUserDO::getUserId, userId)
                    .one();
            if(one != null && one.getIsFixed() == 1){
                map.put(courseId,true);
            }else {
                map.put(courseId,false);
            }
        }
        return map;
    }
}
